<?php

namespace app\api\controller;
use app\admin\model\ArithmeticalLog as ArithmeticalLogModel;
use app\api\model\BaseConfig as BaseConfigModel;
use app\api\model\Member as MemberModel;
use app\api\model\MemberArithmeticalPower as MemberArithmeticalPowerModel;
use app\api\model\MemberLevel as MemberLevelModel;
use app\api\model\MiningArithmetical as MiningArithmeticalModel;
USE app\common\common;
use app\common\model\UserMoneyLog as UserMoneyLogModel;
use app\api\model\MiningPledge as MiningPledgeModel;
use think\facade\Db;
use think\cache\driver\Redis;

class MemberArithmeticalPower extends Baek
{

    /**
     * 订单列表
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function order_list(){
        $page  = $this->request->post('page', '', 'intval');  //页码
        $limit  = $this->request->post('limit', '', 'intval');  //页面数量
        $list = MemberArithmeticalPowerModel::getList($this->mid,$page,$limit);
        return api_success($list);
    }

    /**
     * 创建算例矿机订单
     * @return \think\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function pay(){
        $maid  = $this->request->post('id', '', 'intval');  //算力矿机ID
        $info = MiningArithmeticalModel::getDetails($maid);
        if(empty($info)) return api_error('','No such mining machine',$this->language);   //没有该算力矿机

        //有限制出售数量
        if($info['available_for_sale'] != -1){
            if($info['available_for_sale'] == $info['quantity_sold']) return api_error('','The miner has been sold out',$this->language);
        }

        //有限制最大购买
        if($info['max_possess'] != -1){
            $mem_ari = MemberArithmeticalPowerModel::getMemberAll($this->mid,['maid'=>$maid]);
            if(!empty($mem_ari)){
                $mem_ari = $mem_ari->toArray();
                $sum = $this->count($mem_ari);
                if($info['max_possess'] == $sum) return api_error('','The miner has been sold out',$this->language);
            }
        }

        $id = MemberArithmeticalPowerModel::add($this->mid,$maid,$info);

        //订单创建失败
        if(empty($id)) return api_error('','Order creation failed',$this->language);

        return api_success($id);
    }

    /**
     * 支付算力订单
     * @return \think\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function pay_order(){
        $id  = $this->request->post('id', '', 'intval');  //算力矿机ID
        $info = MemberArithmeticalPowerModel::getMemberDetails($this->mid,$id);
        //该订单不存在
        if(empty($info)) return api_error('','Order does not exist',$this->language);
        //订单已支付
        if($info['pay_status'] == 1) return api_error('','Order paid',$this->language);
        //获取用户详情
        $member = MemberModel::getDetails($this->mid);

        $currency = $info['currency'];
        if($info['currency'] == 2) $currency = 5;
        $currency = common::key_currency($currency);

        //获取矿机详情
        $MiningArithmetical = MiningArithmeticalModel::getDetails($info['maid'])->toArray();
        if($MiningArithmetical['available_for_sale'] > -1){
            if($MiningArithmetical['available_for_sale'] <= $MiningArithmetical['quantity_sold']) return api_error('','Sold out',$this->language);
        }

        Db::startTrans();
        try {
            //扣款
            $pay_status = UserMoneyLogModel::change($this->mid,$currency,-$info['money'],'pay_mining',$info['id'],'购买矿机，支付：'.$info['money']);

            if($pay_status != true){  //支付失败
                Db::rollback();
                return api_error($pay_status,'Purchase failed',$this->language);
            }else{
                //支付失败
                if(is_array($pay_status)){
                    Db::rollback();
                    return api_error($pay_status,'Purchase failed',$this->language);
                }
            }
            //修改矿机状态
            MemberArithmeticalPowerModel::where('id',$info['id'])->update(['pay_status'=>1,'update_time'=>date('Y-m-d H:i:s',time())]);
            //添加已售数量
            MiningArithmeticalModel::inventory_deduction($info['maid']);

            //销毁
            $redis = new Redis(config('cache.stores.redis'));
            $destroy = $redis->get('adc_destroy');
            $destroy = bcadd($destroy,$info['money'],8);
            $redis->set('adc_destroy',$destroy);

            //有上级用户
            if(!empty($member['pid'])){
                //赠送直推算力大于0
                if($MiningArithmetical['push_arithmetical'] > 0){
                    $p_All = MemberArithmeticalPowerModel::getMemberAll($member['pid'],['pay_status'=>1]);
                    //账号已激活
                    if(!empty($p_All)){
                        //赠送数量
                        UserMoneyLogModel::change($member['pid'],'recommended_computing',$MiningArithmetical['push_arithmetical'],'Direct calculation force',$id,'直推获得算力');
                    }
                }
                //赠送直推算力大于0
                if($MiningArithmetical['indirect_arithmetical'] > 0){
                    //查询用户详情
                    $pmember = MemberModel::getDetails($member['pid']);
                    if(!empty($pmember['pid'])){
                        //赠送数量
                        UserMoneyLogModel::change($pmember['pid'],'recommended_computing',$MiningArithmetical['indirect_arithmetical'],'Inter-calculation force',$id,'间推获得算力');
                    }
                }

                //所有等级
                $level_List = MemberLevelModel::getMemberList();
                $level = [];
                $level['max'] = 0;  //最大等级
                //循环用户等级
                foreach ($level_List as $v){
                    $level[$v['id']] = $v;
                    if($v['level'] == 0) $level[0] = $v;    //初始等级
                    if($level['max'] < $v['level']) $level['max'] = $v['level'];
                }
                //团队奖励算力矿机
                $superior_extremely = MemberModel::superior_extremely($this->mid,$MiningArithmetical['arithmetical']);

                if(!empty($superior_extremely['range'])){
                    foreach ($superior_extremely['range'] as $v){   //发放极差奖
                        UserMoneyLogModel::change($v['mid'],'recommended_computing',$v['num'],'Voting power of community nodes',$id,'矿机极差奖励');
                    }
                }

                if(!empty($superior_extremely['current'])) {  //发放同级奖
                    foreach ($superior_extremely['current'] as $v) {
                        UserMoneyLogModel::change($v['mid'], 'recommended_computing', $v['num'], 'Voting power of peer nodes', $id, '矿机同级奖励');
                    }
                }

            }


            //提交事务
            Db::commit();
            return api_success();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return api_error('','Purchase failed',$this->language);
        }
    }

    /**
     * 矿机质押 / 归还矿机质押
     * @return \think\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function pledge(){
        $id  = $this->request->post('id', '', 'intval');  //算力矿机订单ID
        $type  = $this->request->post('type', '', 'intval');  //1: 质押 2：返回质押
        $money  = $this->request->post('money', '', 'intval');  //1: 质押数量 2：返回质押数量
        $info = MemberArithmeticalPowerModel::getDetails($id);
        //没有该矿机
        if(empty($info)) return api_error('','No such miner',$this->language);
        $info = $info->toArray();
        //该矿机不是此用户
        if($info['mid'] != $this->mid) return api_error('','No such miner',$this->language);

        //质押
        if($type == 1){
//            if($info['pledge'] == 2) return api_error('','Pledged',$this->language);
            //查询用户余额
            $member_wallte = MemberModel::wallet($this->mid);
            if($member_wallte['adc'] < $money) return api_error('','Insufficient balance, unable to pledge',$this->language);  //余额不足

            //计算剩可质押数量
            $arithmetical_power = bcsub($info['arithmetical_power'],$info['pledge_money'],8);
            if($arithmetical_power < $money) return api_error('','Cannot pledge in excess',$this->language);  //无法超量质押

            Db::startTrans();
            try {
                //扣除余额
                $change_status = UserMoneyLogModel::change($this->mid,'adc',-$money,'Pledge mining machine',$id,'质押矿机');
                if(!$change_status){
                    Db::rollback();
                    return api_error($change_status,'Fee deduction failed',$this->language);    //扣费失败
                }
                //质押矿机
                $pledge_money = bcadd($info['pledge_money'],$money);
                MemberArithmeticalPowerModel::pledge($id,$pledge_money);

                //记录本次质押
                MiningPledgeModel::add($info['mid'],$info['maid'],$id,$money,1);

                //发放质押奖励
                self::zhiya_jiangli($info,$id,$money);

                //提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                return api_error('','Fee deduction failed',$this->language);
            }
        }

        //返回质押
        if($type == 2){
            if($info['pledge'] != 2) return api_error('','Not pledged yet',$this->language);    //尚未质押
            $pledge_return = BaseConfigModel::config_data('pledge_return');

            if($money <= 0) return api_error('','invalid operation',$this->language);   //无效操作,取出质押数不能为0 或小于0

            if($info['pledge_money'] < $money) return api_error('','The pledge quantity has been exceeded',$this->language);    //已超出质押数量

            Db::startTrans();
            try {
                if($pledge_return != 0){

                    //计算返回质押金额
                    $adc_money = bcmul($money,bcdiv($pledge_return,100,8),8);
                    //计算返回比例
                    $change_status = UserMoneyLogModel::change($this->mid,'adc',$adc_money,'Return mining machine pledge',$id,'返回矿机质押');
                    if(!$change_status){    //质押金归还失败
                        Db::rollback();
                        return api_error('','Failed to return pledge',$this->language);
                    }
                }

                //销毁
                $redis = new Redis(config('cache.stores.redis'));
                $destroy = $redis->get('adc_destroy');
                //计算已扣除数量
                $destroy_pledge = bcsub($money,$adc_money,8);
                $destroy = bcadd($destroy,$destroy_pledge,8);
                $redis->set('adc_destroy',$destroy);

                //计算剩余质押数量
                $pledge_money = bcsub($info['pledge_money'],$money,8);
                //返回质押
                MemberArithmeticalPowerModel::cancel_pledge($id,$pledge_money);
                //记录本次质押
                MiningPledgeModel::add($info['mid'],$info['maid'],$id,-$money,1);

                //发放质押奖励
                self::zhiya_jiangli($info,$id,-$money);

                //提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                return api_error('','Fee deduction failed',$this->language);
            }
        }

        return api_success();

    }

    /**
     * 发放质押奖励
     * @param $info 矿机订单详情
     * @param $id   矿机订单ID
     * @param $money    质押金额
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private static function zhiya_jiangli($info,$id,$money){

        //获取矿机详情
        $MiningArithmetical = MiningArithmeticalModel::getDetails($info['maid']);
        //计算 直推、间推 赠送比例
        if(!empty($MiningArithmetical)){
            $MiningArithmetical = $MiningArithmetical->toArray();

            //查询用户详情
            $member = MemberModel::getDetails($info['mid'])->toArray();
            if($member['pid'] > 0){ //上级用户不为空

                $suanli = bcmul($money,$MiningArithmetical['pledge_multiple'],8);   //计算质押总算力
                //直推
                if( $MiningArithmetical['push_arithmetical'] > 0){//直推奖励
                    $push_arithmetical = bcdiv($MiningArithmetical['push_arithmetical'],$MiningArithmetical['arithmetical'],8); //比例
                    $push_suanli = bcmul($suanli,$push_arithmetical,8);
                    //发放直推质押奖励
                    MiningPledgeModel::add($member['pid'],$info['maid'],$id,$push_suanli,2);

                }
                //间推
                $p_member = MemberModel::getDetails($member['pid']);
                if(!empty($p_member)){
                    $p_member = $p_member->toArray();
                    if($MiningArithmetical['indirect_arithmetical'] > 0 && $p_member['pid'] > 0) {   //间推奖励
                        $indirect_arithmetical = bcdiv($MiningArithmetical['indirect_arithmetical'],$MiningArithmetical['arithmetical'],8); //比例
                        $indirect_suanli = bcmul($suanli,$indirect_arithmetical,8);
                        //发放间推质押奖励
                        MiningPledgeModel::add($p_member['pid'],$info['maid'],$id,$indirect_suanli,2);
                    }
                }

                //团队质押奖励发放
                $superior_extremely = MemberModel::superior_extremely($info['mid'],$suanli);
                if(!empty($superior_extremely['range'])){   //发放极差奖
                    foreach ($superior_extremely['range'] as $v){
                        MiningPledgeModel::add($v['mid'],$info['maid'],$id,$v['num'],2);
                    }
                }
                if(!empty($superior_extremely['current'])) {  //发放同级奖
                    foreach ($superior_extremely['current'] as $v) {
                        MiningPledgeModel::add($v['mid'],$info['maid'],$id,$v['num'],2);
                    }
                }

            }
        }
    }


    /**
     * 用户矿机产出列表
     * @return \think\Response
     * @throws \think\db\exception\DbException
     *
     */
    function node_output(){
        $limit  = $this->request->post('limit', 20, 'intval');
        $page = $this->request->post('page', 1, 'intval');
        $order  = $this->request->post('order', '', 'serach_in');	//排序字段
        $sort  = $this->request->post('sort', '', 'serach_in');		//排序方式

        $orderby = ($sort && $order) ? $sort.' '.$order : 'id desc';
        //获取节点产出记录
        $res = ArithmeticalLogModel::getList($page,$limit,['mid'=>$this->mid],$orderby);
        $type = (new ArithmeticalLogModel())->type;
        $member = MemberModel::getDetails($this->mid);

        $sys_address = 'ADC0000000000000000000000000000000000000';  //系统方
        foreach ($res['data'] as &$v){
            $v['type'] = $type[$v['type']][$this->language];
            $v['send_address'] = $sys_address;
            $v['receive_address'] = $member->username;
            $v['height'] = bcadd(14565,$v['id']);
        }

        return api_success($res);
    }
}